﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace game
{
    public class ModelUnit
    {
        public Model Model { get; protected set; }
        public BoundingSphere BSphere { get; protected set; }
        public Matrix BaseMatrix { get; protected set; }
        public Effect[] DefaultEffects { get; protected set; }

        public Texture GlowTexture { get; set; }

        protected Texture2D bumpMap;
        protected Texture2D normalMap;
        protected Texture2D diffuseMap;
        protected Material material;

        public Matrix[] transforms { get; protected set; }

        protected static bool debugSet = false;

        public ModelUnit(Model model, Matrix baseMatrix)
        {
            this.Model = model;
            this.BaseMatrix = baseMatrix;

            Model.Root.Transform *= baseMatrix;

            transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);

            BSphere = new BoundingSphere();
            foreach (ModelMesh mesh in model.Meshes)
            {
                BSphere = BoundingSphere.CreateMerged(BSphere,
                    mesh.BoundingSphere.Transform(transforms[mesh.ParentBone.Index]));
            }


            int parts = 0;
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    parts++;
                }
            }
            DefaultEffects = new Effect[parts];
            parts = 0;
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    DefaultLightShader shader = new DefaultLightShader();
                    shader.Initialize();
                    BasicEffect effect = ((BasicEffect)part.Effect);

                    shader.DiffuseMap.SetValue(effect.Texture);

                    shader.DiffMat.SetValue(new Vector4(effect.DiffuseColor, 1.0f));
                    shader.SpecMat.SetValue(new Vector4(effect.SpecularColor, 1.0f));
                    shader.SpecPower.SetValue(effect.SpecularPower);
                    shader.AmbMat.SetValue(new Vector4(effect.DiffuseColor, 1.0f));

                    shader.DiffLight.SetValue(new Vector4(1.1f, 1, 1, 1));
                    shader.SpecLight.SetValue(new Vector4(1, 1, 1, 1));
                    shader.AmbLight.SetValue(new Vector4(0.1f, 0.1f, 0.1f, 1));
                    //shader.Attenuation012.SetValue(new Vector3(1, 0, 0));
                    shader.MainLightDirW.SetValue(new Vector3(1, 1, -1));

                    DefaultEffects[parts] = part.Effect;
                    part.Effect = shader.Effect;
                    part.Tag = shader;
                    parts++;
                }
            }
        }

        public ModelUnit(Model model)
            : this(model, Matrix.Identity)
        {
        }

        public void SetDiffuseMapping(Texture2D map)
        {
            diffuseMap = map;
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    if (part.Effect is BasicEffect)
                    {
                        ((BasicEffect)part.Effect).Texture = map;
                        ((BasicEffect)part.Effect).TextureEnabled = true;
                    }
                    else
                    {
                        (part.Tag as DefaultLightShader).DiffuseMap.SetValue(map);
                    }
                }
            }
        }

        public void SetNormalMapping(Texture2D map)
        {
            normalMap = map;
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    if (part.Effect is BasicEffect)
                    {

                    }
                    else if (part.Tag is DefaultLightShader)
                    {
                        (part.Tag as DefaultLightShader).SetNormalMapping(map);
                    }
                }
            }

        }

        public void SetParallaxNormalMapping(Texture2D aBumpMap, Texture2D aNormalMap)
        {
            bumpMap = aBumpMap;
            normalMap = aNormalMap;
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    if (part.Effect is BasicEffect)
                    {

                    }
                    else if (part.Tag is DefaultLightShader)
                    {
                        (part.Tag as DefaultLightShader).SetParallaxNormalMapping(aBumpMap, aNormalMap);
                    }
                }
            }

        }

        public void SetMaterial(Material mat)
        {
            material = mat;

            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    if (part.Effect is BasicEffect)
                    {
                        BasicEffect be = (BasicEffect)part.Effect;
                        be.DiffuseColor = mat.Diffuse;
                        be.EmissiveColor = mat.Emissive;
                        be.SpecularColor = mat.Specular;
                        be.SpecularPower = mat.SpecPower;
                        be.Alpha = mat.Alpha;
                    }
                    else
                    {
                        (part.Tag as DefaultLightShader).DiffMat.SetValue(new Vector4(mat.Diffuse, 1));
                        (part.Tag as DefaultLightShader).AmbMat.SetValue(new Vector4(mat.Ambient, 1));
                        (part.Tag as DefaultLightShader).SpecMat.SetValue(new Vector4(mat.Specular, 1));
                        (part.Tag as DefaultLightShader).SpecPower.SetValue(mat.SpecPower);
                    }
                }
            }

            //foreach (Effect e in DefaultEffects)
            //{
            //    if (e is BasicEffect)
            //    {
            //        BasicEffect be = (BasicEffect)e;
            //        be.DiffuseColor = material.Diffuse;
            //        be.EmissiveColor = material.Emissive;
            //        be.SpecularColor = material.Specular;
            //        be.SpecularPower = material.SpecPower;
            //        be.Alpha = material.Alpha;
            //    }
            //}
        }

        public void SetDefaultEffects()
        {
            int partIndex = 0;
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    part.Effect = DefaultEffects[partIndex];
                    partIndex++;
                }
            }
        }

        public void SetEffect(Effect effect)
        {
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    part.Effect = effect;
                }
            }
        }
    }
}
